﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IBS.Model;
using IBS.ServiceContracts;

namespace IBS.Bll.OperationDay
{
    public class OperationDayService : ServiceBase, IOperationDayService, IOperationDayServiceProcessing
    {
        private readonly IAccountService _accountService;
        private readonly ICurrencyService _currencyService;

        #region Constructors
        public OperationDayService(IIbsContext context, IAccountService accountService, ICurrencyService currencyService)
            : base(context)
        {
            _accountService = accountService;
            _currencyService = currencyService;
        }

        #endregion
        #region Main

        public void UpdateClientBalances()
        {
            Processor.UpdateClientBalances();
            _context.SaveChanges();
        }

        public decimal CommonBalance()
        {
            var result = Processor.CommonBalance();
            _context.SaveChanges();
            return result;
        }

        public decimal CommonBalance(string ISO)
        {
            var result = Processor.CommonBalance(ISO);
            _context.SaveChanges();
            return result;
        }

        public void UpdateCurrencyRates()
        {
            Processor.UpdateCurrencyRates();
            _context.SaveChanges();
        }

        private IOperationDayServiceProcessing _processor;
        public IOperationDayServiceProcessing Processor
        {
            get { return _processor ?? (_processor = this); }
        }
        #endregion

        #region Processing

        void IOperationDayServiceProcessing.UpdateClientBalances()
        {
            foreach (var client in _context.Clients)
            {
                foreach (var account in client.Account)
                {
                    Balance lastBalance = null,
                            newBalance = new Balance()
                    {
                        AccountId = account.Id,
                        Date = DateTime.Now
                    };
                    try
                    {
                        lastBalance = _accountService.GetCurrentBalance(account);
                        //If account doesn't have  todate balance then create it
                        if (lastBalance.Date.Date != DateTime.Now.Date)
                        {
                            newBalance.Amount = lastBalance.Amount;
                            account.Balance.Add(newBalance);
                        }

                    }
                    catch (BusinessException)
                    {
                        //Account doesn't have any balance
                        account.Balance.Add(newBalance);
                    }

                }
            }

        }

        decimal IOperationDayServiceProcessing.CommonBalance()
        {
            return Enumerable.Sum(_context.Currencies.Select(c => c.ISO), iso => Processor.CommonBalance(iso));
        }

        decimal IOperationDayServiceProcessing.CommonBalance(string ISO)
        {
            return _context.Accounts.Where(a => a.Currency != null && a.Currency.ISO == ISO).Sum(
                a => _accountService.GetCurrentBalance(a).Amount);
        }

        void IOperationDayServiceProcessing.UpdateCurrencyRates()
        {
            foreach (var currency in _context.Currencies.ToList())
            {
                CurrencyExchangeRate lastRates = null;

                try
                {
                    lastRates = _currencyService.GetCurrentRates(currency.ISO);

                }
                catch (BusinessException)
                {
                    lastRates = new CurrencyExchangeRate();

                    //If currency doesn't have any currency rates then create defaul
                    if (currency.ISO == "USD")
                    {
                        lastRates.AskRate = 8500m;
                        lastRates.BidRate = 8300m;
                    }
                    else
                    {
                        lastRates.AskRate = 1m;
                        lastRates.BidRate = 1m;
                    }
                }

                var newRates = new CurrencyExchangeRate()
                                       {
                                           AskRate = lastRates.AskRate,
                                           BidRate = lastRates.BidRate,
                                           CurrencyId = currency.Id,
                                           Date = DateTime.Now
                                       };
                _context.CurrencyExchangeRates.AddObject(newRates);
            }
            _context.SaveChanges();
        }
    }
        #endregion
}
